<?php

namespace app\common\services\table;

use think\helper\Str;
use think\Model;

class BaseTable
{
    // 表名
    protected string $tableName;
    // 设置的参数
    protected array $fields = [];
    // 启用数据库字段注释
    protected bool $useComment = true;
    /**
     * 模型
     * @var Model|null
     */
    protected $model = null;

    // 常用字段翻译
    public $fieldComment = [
        'id'          => 'ID',
        'create_time' => '创建时间',
        'update_time' => '更新时间',
        'delete_time' => '删除时间',
        'weigh'       => '权重',
        'sort'        => '排序',
        'status'      => '状态',
        'appid'       => '应用ID',
        'config'      => '配置',
        'plaid'       => '平台ID',
    ];

    /**
     * 输入框类型的识别规则
     * @var array
     */
    protected $inputTypeRule = [
        [
            'type'   => ['tinyint', 'int', 'enum'],
            'suffix' => ['switch', 'toggle'],
            'prefix' => ['is_', 'has_', 'has'],
            'value'  => 'switches',
        ],
        [
            'column_type' => ['tinyint(1)', 'char(1)', 'tinyint(1) unsigned'],
            'suffix'      => ['switch', 'toggle'],
            'prefix'      => ['is_', 'has_', 'has'],
            'value'       => 'switches',
        ],
        // 富文本-识别规则和textarea重合,优先识别为富文本
        [
            'type'   => ['longtext', 'text', 'mediumtext', 'smalltext', 'tinytext', 'bigtext'],
            'suffix' => ['content', 'editor'],
            'value'  => 'dkTinyEditor',
        ],
        // textarea
        [
            'type'   => ['varchar'],
            'suffix' => ['textarea', 'multiline', 'rows'],
            'value'  => 'textarea',
        ],
        // TODO Array
        [
            'suffix' => ['array'],
            'value'  => 'array',
        ],
        // TODO 时间选择器-字段类型为int同时以['time', 'datetime']结尾
        [
            'type'  => ['timestamp','int'],
            'suffix' => ['time'],
            'value' => 'timestamp'
        ],
        [
            'type'   => ['int', 'datetime','timestamp'],
            'suffix' => ['datetime'],
            'value'  => 'datetime',
        ],
        // 时间选择器-字段类型为int同时以['time']结尾
        //        ['type' => ['int'], 'suffix' => ['time'], 'value' => 'time'],
        // 时间选择
        ['type' => ['time'], 'value' => 'time'],
        ['type' => ['date'], 'value' => 'date'],
        ['type' => ['year'], 'value' => 'year'],
        [
            'suffix' => ['select', 'list', 'data'],
            'value'  => 'select',
        ],
        [
            'suffix' => ['selects', 'multi', 'lists'],
            'value'  => 'selects',
        ],
        // 远程下拉选择器
        ['suffix' => ['_id'], 'value' => 'remoteSelect'],
        ['suffix' => ['_ids'], 'value' => 'remoteSelects'],
        // 附件
        ['suffix' => ['image', 'avatar'], 'value' => 'dkImage'],
        ['suffix' => ['images', 'avatars'], 'value' => 'dkImageList'],
        ['suffix' => ['file'], 'value' => 'dkFile'],
        ['suffix' => ['files'], 'value' => 'dkFileList'],
        ['suffix' => ['audio'], 'value' => 'dkAudio'],
        ['suffix' => ['audios'], 'value' => 'dkAudioList'],
        ['suffix' => ['video'], 'value' => 'dkVideo'],
        ['suffix' => ['videos'], 'value' => 'dkVideoList'],
        ['suffix' => ['icon'], 'value' => 'DkIconInput'],
        // 单选框
        [
            'column_type' => ['tinyint(1)', 'char(1)', 'tinyint(1) unsigned'],
            'suffix'      => ['status', 'state', 'type'],
            'value'       => 'radio',
        ],
        // 数字输入框
        ['suffix' => ['number', 'int', 'num'], 'value' => 'number'],
        [
            'type'  => ['bigint', 'int', 'mediumint', 'smallint', 'tinyint', 'decimal', 'double', 'float'],
            'value' => 'number',
        ],
        // 富文本-低权重
        [
            'type'  => ['longtext', 'text', 'mediumtext', 'smalltext', 'tinytext', 'bigtext'],
            'value' => 'textarea',
        ],
        // 单选框-低权重
        ['type' => ['enum'], 'value' => 'radio'],
        // 多选框
        ['type' => ['set'], 'value' => 'checkbox'],
        // 颜色选择器
        ['suffix' => ['color'], 'value' => 'color'],
        ['suffix' => ['url', 'link'], 'value' => 'dkUrlInput']
    ];


    public function __construct(Model $model)
    {
        $name = $model->getName();
        $this->tableName = Str::snake($name);
        $this->model = $model;
    }

    protected function getTableColumnsDataType($column)
    {
        if (isset($column['render']) && $column['render']) {
            return $column['render'];
        }
        if (stripos($column['Field'], 'id') !== false
            && stripos($column['Extra'], 'auto_increment') !== false) {
            return 'pk';
        } elseif ($column['Field'] == 'weigh') {
            return 'weigh';
        } elseif (in_array($column['Field'], ['createtime', 'updatetime', 'create_time', 'update_time'])) {
            return 'datetime';
        }
        // 输入框类型的识别规则
        foreach ($this->inputTypeRule as $item) {
            $typeBool = true;
            $suffixBool = true;
            $columnTypeBool = true;
            if (isset($item['type']) && $item['type'] && !in_array($this->getFieldType($column['Type']), $item['type'])) {
                $typeBool = false;
            }
            // 匹配后缀
            if (isset($item['suffix']) && $item['suffix']) {
                $suffixBool = $this->isMatchSuffix($column['Field'], $item['suffix']);
            }
            // 匹配前缀
            if (isset($item['prefix']) && $item['prefix']) {
                $prefixBool = $this->isMatchPrefix($column['Field'], $item['prefix']);
            }
            if (isset($item['column_type']) && $item['column_type'] && !in_array($column['Type'], $item['column_type'])) {
                $columnTypeBool = false;
            }
            if ($typeBool && $suffixBool && $columnTypeBool) {
                return $item['value'];
            }
            if ($prefixBool) {
                return $item['value'];
            }
        }
        return 'input';
    }

    /**
     * 判断是否符合指定后缀
     *
     * @param string $field 字段名称
     * @param string|array $suffixArr 后缀
     * @return bool
     */
    protected function isMatchSuffix(string $field, string|array $suffixArr): bool
    {
        $suffixArr = is_array($suffixArr) ? $suffixArr : explode(',', $suffixArr);
        foreach ($suffixArr as $v) {
            if (preg_match("/$v$/i", $field)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 判断是否符合指定前缀
     * Create by :  刘泓宾<514660094@qq.com>
     * @param string $field
     * @param string|array $prefixArr
     * @return bool
     */
    protected function isMatchPrefix(string $field, string|array $prefixArr): bool
    {
        $prefixArr = is_array($prefixArr) ? $prefixArr : explode(',', $prefixArr);
        foreach ($prefixArr as $v) {
            if (preg_match("/^$v/i", $field)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取字段类型
     * @param $str
     * @return string
     */
    protected function getFieldType($str)
    {
        $start = strpos($str, '('); // 查找左括号的位置
        if ($start !== false) {
            $end = strrpos($str, ')'); // 查找右括号的位置
            if ($end !== false && $end > $start + 1) {
                return substr_replace($str, '', $start, $end - $start + 2); // 将左括号及其内容替换为空字符串
            }
        }
        return $str;
    }

    /**
     * 为二维码数组添加键
     * @param $array
     * @param $key
     * @return array
     */
    protected function getKeyArray($array, $key)
    {
        $new_array = [];
        foreach ($array as $value) {
            $new_array[$value[$key]] = $value;
        }
        return $new_array;
    }

    /**
     * 去掉键值数组的键
     * @param $array
     * @return array
     */
    protected function getOnlneArray($array)
    {
        $new_array = [];
        foreach ($array as $value) {
            $new_array[] = $value;
        }
        return $new_array;
    }

    public function field(string|array $fieldList)
    {
        if (is_string($fieldList)) {
            $this->fields = explode(',', $fieldList);
        } else if (is_array($fieldList)) {
            $this->fields = $fieldList;
        }
        return $this;
    }
}
